﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Chen.CefWebKit.Tool
{
    public class AdvanceClient
    {
        HttpClient httpclient;
        public int SleepTime = 5000;
        public TimeSpan Timeout = new TimeSpan(0, 0, 5);
        /// <summary>
        /// 是否自动重试（默认否）
        /// </summary>
        public bool UseCheck = false;
        public AdvanceClient(System.Net.CookieContainer container)
        {
            HttpClientHandler HCHandler = new HttpClientHandler();
            HCHandler.CookieContainer = container;
            httpclient = new HttpClient(HCHandler);
            httpclient.Timeout = new TimeSpan(0,0,5);
            //httpclient.DefaultRequestHeaders.Clear();
            //httpclient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36");
            //httpclient.DefaultRequestHeaders.Add("Connection", "keep-alive");
            //httpclient.DefaultRequestHeaders.Add("Cache-Control", "max-age=0");
        }
        enum Method
        {
            Get,
            Post,
            Put
        }
        #region Private
        private async Task<HttpResponseMessage> GetHttpResponse(string url, Method method,string value=null)
        {
            try
            {
                HttpResponseMessage rs;
                if (method == Method.Post)
                {
                    rs = await httpclient.PostAsync(url, new StringContent(value));
                }
                else
                {
                    rs = await httpclient.GetAsync(url);
                }
                if (rs.StatusCode != HttpStatusCode.OK && UseCheck)
                {
                    Thread.Sleep(SleepTime);
                    return await GetHttpResponse(url, method, value);
                }
                return rs;
            }
            catch
            {
                Thread.Sleep(SleepTime);
                //return new HttpResponseMessage() {StatusCode=HttpStatusCode.BadRequest };
                return await GetHttpResponse(url, method, value);
            }
        }
        private async Task<HttpResponseMessage> GetHttpResponse(string url, Method method,CancellationToken cancel, string value = null)
        {
            try
            {
                HttpResponseMessage rs;
                if (method == Method.Post)
                {
                    rs = await httpclient.PostAsync(url, new StringContent(value), cancel);
                }
                else
                {
                    rs = await httpclient.GetAsync(url, cancel);
                }
                if (rs.StatusCode != HttpStatusCode.OK && UseCheck)
                {
                    Thread.Sleep(SleepTime);
                    return await GetHttpResponse(url, method, cancel,value);
                }
                return rs;
            }
            catch(Exception ex)
            {
                if (ex.Message.Contains("已取消一个任务"))
                {
                    return null;
                }
                Thread.Sleep(SleepTime);
                //return new HttpResponseMessage() {StatusCode=HttpStatusCode.BadRequest };
                return await GetHttpResponse(url, method, cancel, value);
            }
        }
        #endregion

        /// <summary>
        /// 通过Get方式提交,异步获取Html
        /// </summary>
        /// <param name="url">Url</param>
        /// <param name="encode">页面编码</param>
        /// <returns></returns>
        public async Task<string> GetStringAsync(string url,Encoding encode = null)
        {
            HttpResponseMessage rs = await GetHttpResponse(url,Method.Get);
            Task<Byte[]> _byte = rs.Content.ReadAsByteArrayAsync();
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            return encode.GetString(await _byte);
        }
        /// <summary>
        /// 通过Get方式提交,异步获取Html结果对象
        /// </summary>
        /// <param name="url">Url</param>
        /// <param name="encode">页面编码</param>
        /// <returns></returns>
        public async Task<HttpResult> GetHttpResultAsync(string url, Encoding encode = null, CancellationToken? cancel = null)
        {
            HttpResponseMessage rs;
            if (cancel == null)
            {
                rs = await GetHttpResponse(url, Method.Get);
            }
            else
            {
                rs = await GetHttpResponse(url, Method.Get, cancel.Value);
            }
            Task<Byte[]> _byte = rs.Content.ReadAsByteArrayAsync();
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            HttpResult hresult = new HttpResult();
            hresult.ByteData = await _byte;
            hresult.Content = encode.GetString(hresult.ByteData);
            hresult.StateCode = Convert.ToInt32(rs.StatusCode);
            hresult.StateReason = rs.ReasonPhrase;
            hresult.IsSuccess = rs.IsSuccessStatusCode;
            hresult.Headers = rs.Headers;
            return hresult;
        }
        /// <summary>
        /// 通过Post方式提交,异步获取Html
        /// </summary>
        /// <param name="url">Url</param>
        /// <param name="value">Post值</param>
        /// <param name="encode">网页编码</param>
        /// <returns></returns>
        public async Task<string> GetStringByPostAsync(string url,string value,Encoding encode = null)
        {
            HttpResponseMessage rs = await GetHttpResponse(url,Method.Post,value);
            Task<Byte[]> _byte = rs.Content.ReadAsByteArrayAsync();
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            return encode.GetString(await _byte);
        }
        /// <summary>
        /// 通过Post方式提交,异步获取Html结果对象
        /// </summary>
        /// <param name="url">Url</param>
        /// <param name="value">Post值</param>
        /// <param name="encode">网页编码</param>
        /// <returns></returns>
        public async Task<HttpResult> GetHttpResultByPostAsync(string url, string value, Encoding encode = null)
        {
            HttpResponseMessage rs = await GetHttpResponse(url,Method.Post,value);
            Task<Byte[]> _byte = rs.Content.ReadAsByteArrayAsync();
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            HttpResult hresult = new HttpResult();
            hresult.ByteData = await _byte;
            hresult.Content = encode.GetString(hresult.ByteData);
            hresult.StateCode = Convert.ToInt32(rs.StatusCode);
            hresult.StateReason = rs.ReasonPhrase;
            hresult.IsSuccess = rs.IsSuccessStatusCode;
            return hresult;
        }
        public string GetString(string url, Encoding encode = null)
        {
            Task<string> _s = GetStringAsync(url, encode);
            _s.Wait();
            return _s.Result;
        }
        public void AddHead(string key,string value)
        {
            httpclient.DefaultRequestHeaders.Add(key, value);
        }
    }
    public class HttpResult
    {
        public string Content { get; set; }
        public byte[] ByteData { get; set; }
        public int StateCode { get; set; }
        public string StateReason { get; set; }
        public bool IsSuccess { get; set; }
        public HttpResponseHeaders Headers { get; set; }
    }
}
